/**
 * 统计数据管理API - 后台管理
 * 提供首页统计数据的查询功能
 */

const Framework = require("../../framework/node-core-framework.js");
const dayjs = require('dayjs');

module.exports = {
  /**
   * @swagger
   * /admin_api/statistics/overview:
   *   get:
   *     summary: 获取今日统计概览
   *     description: 获取指定设备今日的投递、找工作、聊天、执行中任务数量
   *     tags: [后台-统计管理]
   *     parameters:
   *       - in: query
   *         name: deviceSn
   *         required: true
   *         schema:
   *           type: string
   *         description: 设备SN码
   *     responses:
   *       200:
   *         description: 获取成功
   */
  'GET /statistics/overview': async (ctx) => {
    const models = Framework.getModels();
    const { apply_records, job_postings, chat_records, task_status, op } = models;
    const { deviceSn } = ctx.getQuery();

    if (!deviceSn) {
      return ctx.fail('设备SN码不能为空');
    }

    const todayStart = dayjs().startOf('day').toDate();
    const todayEnd = dayjs().endOf('day').toDate();

    const [
      applyCount,
      jobSearchCount,
      chatCount,
      runningTaskCount
    ] = await Promise.all([
      apply_records.count({
        where: {
          sn_code: deviceSn,
          applyTime: {
            [op.gte]: todayStart,
            [op.lte]: todayEnd
          }
        }
      }).catch(err => {
        console.error('[统计] 查询投递数量失败:', err);
        return 0;
      }),
      job_postings.count({
        where: {
          sn_code: deviceSn,
          create_time: {
            [op.gte]: todayStart,
            [op.lte]: todayEnd
          }
        }
      }).catch(err => {
        console.error('[统计] 查询找工作数量失败:', err);
        return 0;
      }),
      chat_records.count({
        where: {
          sn_code: deviceSn,
          direction: 'sent',
          sendTime: {
            [op.gte]: todayStart,
            [op.lte]: todayEnd
          }
        }
      }).catch(err => {
        console.error('[统计] 查询聊天数量失败:', err);
        return 0;
      }),
      task_status.count({
        where: {
          sn_code: deviceSn,
          status: 'running'
        }
      }).catch(err => {
        console.error('[统计] 查询任务数量失败:', err);
        return 0;
      })
    ]);

    return ctx.success({
      applyCount,
      jobSearchCount,
      chatCount,
      runningTaskCount
    });
  },

  /**
   * @swagger
   * /admin_api/statistics/daily:
   *   post:
   *     summary: 获取按天统计的数据
   *     description: 获取指定设备指定时间范围内按天统计的数据，用于图表展示
   *     tags: [后台-统计管理]
   *     requestBody:
   *       required: true
   *       content:
   *         application/json:
   *           schema:
   *             type: object
   *             required:
   *               - deviceSn
   *             properties:
   *               deviceSn:
   *                 type: string
   *                 description: 设备SN码
   *               days:
   *                 type: integer
   *                 description: 统计最近几天（例如7天）
   *               startDate:
   *                 type: string
   *                 description: 开始日期 (YYYY-MM-DD)
   *               endDate:
   *                 type: string
   *                 description: 结束日期 (YYYY-MM-DD)
   *     responses:
   *       200:
   *         description: 获取成功
   */
  'POST /statistics/daily': async (ctx) => {
    const models = Framework.getModels();
    const { apply_records, job_postings, chat_records, op } = models;
    const { deviceSn, days, startDate, endDate } = ctx.getBody();

    if (!deviceSn) {
      return ctx.fail('设备SN码不能为空');
    }

    let start;
    let end;
    if (days) {
      const maxDays = Math.min(days, 30);
      end = dayjs().endOf('day').toDate();
      start = dayjs().subtract(maxDays - 1, 'day').startOf('day').toDate();
    } else if (startDate && endDate) {
      start = dayjs(startDate).startOf('day').toDate();
      end = dayjs(endDate).endOf('day').toDate();
      const diffDays = dayjs(end).diff(dayjs(start), 'day') + 1;
      if (diffDays > 30) {
        end = dayjs(start).add(29, 'day').endOf('day').toDate();
      }
    } else {
      end = dayjs().endOf('day').toDate();
      start = dayjs().subtract(6, 'day').startOf('day').toDate();
    }

    const [allApplies, allJobs, allChats] = await Promise.all([
      apply_records.findAll({
        where: {
          sn_code: deviceSn,
          applyTime: {
            [op.gte]: start,
            [op.lte]: end
          }
        },
        attributes: ['applyTime'],
        raw: true
      }).catch(err => {
        console.error('[统计] 查询投递记录失败:', err);
        return [];
      }),
      job_postings.findAll({
        where: {
          sn_code: deviceSn,
          create_time: {
            [op.gte]: start,
            [op.lte]: end
          }
        },
        attributes: ['create_time'],
        raw: true
      }).catch(err => {
        console.error('[统计] 查询岗位记录失败:', err);
        return [];
      }),
      chat_records.findAll({
        where: {
          sn_code: deviceSn,
          direction: 'sent',
          sendTime: {
            [op.gte]: start,
            [op.lte]: end
          }
        },
        attributes: ['sendTime'],
        raw: true
      }).catch(err => {
        console.error('[统计] 查询聊天记录失败:', err);
        return [];
      })
    ]);

    const dates = [];
    const applyData = [];
    const jobSearchData = [];
    const chatData = [];

    let currentDate = dayjs(start);
    while (currentDate.isBefore(end) || currentDate.isSame(end, 'day')) {
      const dateStr = currentDate.format('YYYY-MM-DD');
      const dayStart = currentDate.startOf('day');
      const dayEnd = currentDate.endOf('day');

      const applyCount = allApplies.filter(item => {
        const itemDate = dayjs(item.applyTime);
        return itemDate.isSameOrAfter(dayStart) && itemDate.isSameOrBefore(dayEnd);
      }).length;

      const jobCount = allJobs.filter(item => {
        const itemDate = dayjs(item.create_time);
        return itemDate.isSameOrAfter(dayStart) && itemDate.isSameOrBefore(dayEnd);
      }).length;

      const chatCount = allChats.filter(item => {
        const itemDate = dayjs(item.sendTime);
        return itemDate.isSameOrAfter(dayStart) && itemDate.isSameOrBefore(dayEnd);
      }).length;

      dates.push(dateStr);
      applyData.push(applyCount);
      jobSearchData.push(jobCount);
      chatData.push(chatCount);

      currentDate = currentDate.add(1, 'day');
    }

    return ctx.success({
      dates,
      applyData,
      jobSearchData,
      chatData
    });
  },

  /**
   * @swagger
   * /admin_api/statistics/running-tasks:
   *   get:
   *     summary: 获取当前正在执行的任务
   *     description: 获取指定设备当前正在执行的任务及其命令列表
   *     tags: [后台-统计管理]
   *     parameters:
   *       - in: query
   *         name: deviceSn
   *         required: true
   *         schema:
   *           type: string
   *         description: 设备SN码
   *     responses:
   *       200:
   *         description: 获取成功
   */
  'GET /statistics/running-tasks': async (ctx) => {
    const models = Framework.getModels();
    const { task_status, task_commands } = models;
    const { deviceSn } = ctx.getQuery();

    if (!deviceSn) {
      return ctx.fail('设备SN码不能为空');
    }

    // 查询正在执行的任务
    const runningTasks = await task_status.findAll({
      where: {
        sn_code: deviceSn,
        status: 'running'
      },
      order: [['startTime', 'DESC']],
      limit: 10 // 限制最多返回10个任务
    });

    // 为每个任务查询其命令列表
    const tasksWithCommands = await Promise.all(
      runningTasks.map(async (task) => {
        const commands = await task_commands.findAll({
          where: { task_id: task.id },
          order: [
            ['sequence', 'ASC'],
            ['create_time', 'ASC']
          ]
        });

        return {
          taskId: task.id,
          taskName: task.taskName || task.taskType,
          taskType: task.taskType,
          startTime: dayjs(task.startTime).format('YYYY-MM-DD HH:mm:ss'),
          progress: task.progress || 0,
          commands: commands.map(cmd => ({
            commandId: cmd.id,
            commandName: cmd.command_name,
            status: cmd.status || 'pending'
          }))
        };
      })
    );

    return ctx.success(tasksWithCommands);
  },

  /**
   * @swagger
   * /admin_api/statistics/apply:
   *   post:
   *     summary: 获取投递数量统计（按天）
   *     description: 获取指定设备按天的投递数量统计
   *     tags: [后台-统计管理]
   *     requestBody:
   *       required: true
   *       content:
   *         application/json:
   *           schema:
   *             type: object
   *             required:
   *               - deviceSn
   *             properties:
   *               deviceSn:
   *                 type: string
   *               days:
   *                 type: integer
   *     responses:
   *       200:
   *         description: 获取成功
   */
  'POST /statistics/apply': async (ctx) => {
    const models = Framework.getModels();
    const { apply_records, op } = models;
    const { deviceSn, days = 7 } = ctx.getBody();

    if (!deviceSn) {
      return ctx.fail('设备SN码不能为空');
    }

    const maxDays = Math.min(days, 30);
    const end = dayjs().endOf('day').toDate();
    const start = dayjs().subtract(maxDays - 1, 'day').startOf('day').toDate();

    const allApplies = await apply_records.findAll({
      where: {
        sn_code: deviceSn,
        applyTime: {
          [op.gte]: start,
          [op.lte]: end
        }
      },
      attributes: ['applyTime'],
      raw: true
    }).catch(err => {
      console.error('[统计] 查询投递记录失败:', err);
      return [];
    });

    const dates = [];
    const data = [];

    let currentDate = dayjs(start);
    while (currentDate.isBefore(end) || currentDate.isSame(end, 'day')) {
      const dateStr = currentDate.format('YYYY-MM-DD');
      const dayStart = currentDate.startOf('day');
      const dayEnd = currentDate.endOf('day');

      const count = allApplies.filter(item => {
        const itemDate = dayjs(item.applyTime);
        return itemDate.isSameOrAfter(dayStart) && itemDate.isSameOrBefore(dayEnd);
      }).length;

      dates.push(dateStr);
      data.push(count);
      currentDate = currentDate.add(1, 'day');
    }

    return ctx.success({ dates, data });
  },

  /**
   * @swagger
   * /admin_api/statistics/job-search:
   *   post:
   *     summary: 获取找工作数量统计（按天）
   *     description: 获取指定设备按天的找工作数量统计
   *     tags: [后台-统计管理]
   *     requestBody:
   *       required: true
   *       content:
   *         application/json:
   *           schema:
   *             type: object
   *             required:
   *               - deviceSn
   *             properties:
   *               deviceSn:
   *                 type: string
   *               days:
   *                 type: integer
   *     responses:
   *       200:
   *         description: 获取成功
   */
  'POST /statistics/job-search': async (ctx) => {
    const models = Framework.getModels();
    const { job_postings, op } = models;
    const { deviceSn, days = 7 } = ctx.getBody();

    if (!deviceSn) {
      return ctx.fail('设备SN码不能为空');
    }

    const maxDays = Math.min(days, 30);
    const end = dayjs().endOf('day').toDate();
    const start = dayjs().subtract(maxDays - 1, 'day').startOf('day').toDate();

    const allJobs = await job_postings.findAll({
      where: {
        sn_code: deviceSn,
        create_time: {
          [op.gte]: start,
          [op.lte]: end
        }
      },
      attributes: ['create_time'],
      raw: true
    }).catch(err => {
      console.error('[统计] 查询岗位记录失败:', err);
      return [];
    });

    const dates = [];
    const data = [];

    let currentDate = dayjs(start);
    while (currentDate.isBefore(end) || currentDate.isSame(end, 'day')) {
      const dateStr = currentDate.format('YYYY-MM-DD');
      const dayStart = currentDate.startOf('day');
      const dayEnd = currentDate.endOf('day');

      const count = allJobs.filter(item => {
        const itemDate = dayjs(item.create_time);
        return itemDate.isSameOrAfter(dayStart) && itemDate.isSameOrBefore(dayEnd);
      }).length;

      dates.push(dateStr);
      data.push(count);
      currentDate = currentDate.add(1, 'day');
    }

    return ctx.success({ dates, data });
  },

  /**
   * @swagger
   * /admin_api/statistics/chat:
   *   post:
   *     summary: 获取聊天/沟通数量统计（按天）
   *     description: 获取指定设备按天的聊天数量统计
   *     tags: [后台-统计管理]
   *     requestBody:
   *       required: true
   *       content:
   *         application/json:
   *           schema:
   *             type: object
   *             required:
   *               - deviceSn
   *             properties:
   *               deviceSn:
   *                 type: string
   *               days:
   *                 type: integer
   *     responses:
   *       200:
   *         description: 获取成功
   */
  'POST /statistics/chat': async (ctx) => {
    const models = Framework.getModels();
    const { chat_records, op } = models;
    const { deviceSn, days = 7 } = ctx.getBody();

    if (!deviceSn) {
      return ctx.fail('设备SN码不能为空');
    }

    const maxDays = Math.min(days, 30);
    const end = dayjs().endOf('day').toDate();
    const start = dayjs().subtract(maxDays - 1, 'day').startOf('day').toDate();

    const allChats = await chat_records.findAll({
      where: {
        sn_code: deviceSn,
        direction: 'sent',
        sendTime: {
          [op.gte]: start,
          [op.lte]: end
        }
      },
      attributes: ['sendTime'],
      raw: true
    }).catch(err => {
      console.error('[统计] 查询聊天记录失败:', err);
      return [];
    });

    const dates = [];
    const data = [];

    let currentDate = dayjs(start);
    while (currentDate.isBefore(end) || currentDate.isSame(end, 'day')) {
      const dateStr = currentDate.format('YYYY-MM-DD');
      const dayStart = currentDate.startOf('day');
      const dayEnd = currentDate.endOf('day');

      const count = allChats.filter(item => {
        const itemDate = dayjs(item.sendTime);
        return itemDate.isSameOrAfter(dayStart) && itemDate.isSameOrBefore(dayEnd);
      }).length;

      dates.push(dateStr);
      data.push(count);
      currentDate = currentDate.add(1, 'day');
    }

    return ctx.success({ dates, data });
  }
};
